package com.yootk.servlet;

import jakarta.servlet.AsyncContext;
import jakarta.servlet.AsyncEvent;
import jakarta.servlet.AsyncListener;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 异步响应监听
 */
@WebServlet(value = "/asyncListener", asyncSupported = true) // 默认情况下是不开启异步支持的
public class AsyncListenerServlet extends HttpServlet {
    private class WorkerThread implements Runnable {   // 创建一个线程类
        private AsyncContext asyncContext; // 负责最终的异步处理

        public WorkerThread(AsyncContext asyncContext) {
            this.asyncContext = asyncContext;
        }

        @Override
        public void run() { // 进行异步响应
            System.err.println("【WorkerThread.run()】ThreadName = " + Thread.currentThread().getName());
            String msg = this.asyncContext.getRequest().getParameter("info"); // 获取当前用户的请求参数
            try {
                TimeUnit.SECONDS.sleep(2); // 模拟处理延迟
                // 通过异步上下文获取一个响应对象，并且输出响应内容，但是对于异步处理完成之后需要给出一个信号
                this.asyncContext.getResponse().getWriter().println("<h1>【ECHO】" + msg +"</h1>");
                this.asyncContext.complete(); // 异步处理完成
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private class WorkerAsyncListener implements AsyncListener {   // 异步监听操作
        @Override
        public void onComplete(AsyncEvent asyncEvent) throws IOException {
            System.out.println("【WorkerAsyncListener.onComplete()】异步线程处理完毕，接收参数内容：" +
                    asyncEvent.getSuppliedRequest().getParameter("info"));
        }
        @Override
        public void onTimeout(AsyncEvent asyncEvent) throws IOException {
            System.out.println("【WorkerAsyncListener.onTimeout()】异步处理时间超时，接收参数内容：" +
                    asyncEvent.getSuppliedRequest().getParameter("info"));
        }
        @Override
        public void onError(AsyncEvent asyncEvent) throws IOException {
            System.out.println("【WorkerAsyncListener.onError()】异步线程处理错误，接收参数内容：" +
                    asyncEvent.getSuppliedRequest().getParameter("info"));
        }
        @Override
        public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
            System.out.println("【WorkerAsyncListener.onStartAsync()】开启了一个异步处理线程，接收参数内容：" +
                    asyncEvent.getSuppliedRequest().getParameter("info"));
        }
    }

    @Override   // 进行GET请求的处理
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.err.println("【AsyncServlet.doGet()】ThreadName = " + Thread.currentThread().getName());
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        // 所有的AsyncContext相关的处理操作全部都是在ServletRequest接口中定义
        if (req.isAsyncSupported()) { // 判断当前是否支持有异步请求处理能力
            AsyncContext asyncContext = req.startAsync(); // 创建异步处理的上下文对象
            asyncContext.addListener(new WorkerAsyncListener()); // 绑定异步监听
            //asyncContext.setTimeout(200); // 200毫秒应该结束异步操作
            asyncContext.setTimeout(5000);
            asyncContext.start(new WorkerThread(asyncContext)); // 启动异步线程
        } else {
            resp.getWriter().println("<h1>骚蕊，我还不支持异步请求处理，请放过我吧！</h1>");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}
